package activities;

import helper.FBHelper;
import helper.GetMyScheduleHelper;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;

import org.json.JSONArray;
import org.json.JSONException;

import com.facebook.Response;
import com.facebook.Session;
import com.matchcalendar.R;

import dataFormat.CalendarTextData;

import factories.CalendarTextDataFactory;
import fragments.ScheduleFragment;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.SparseArray;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.DatePicker;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;

public class ScheduleActivity extends GlobalActivity {
	private Button buttonNowYearAndMonth;
	private ViewPager schedulePager;
	private SparseArray<ScheduleFragment> scheduleFragmentTable = new SparseArray<ScheduleFragment>();
	private Calendar specificDay = Calendar.getInstance();
	private int schSize = 1000;
	private int schInitPosition = schSize / 2;
	private SensorManager sensorManager;
	private boolean isToday = true;
	private ShakeSensorEventListener ssEventListener = new ShakeSensorEventListener();
	private SparseArray<Set<CalendarTextData>> dayCalDatasMap = new SparseArray<Set<CalendarTextData>>();
	
	public SparseArray<Set<CalendarTextData>> getDayCalDatasMap() {
		return dayCalDatasMap;
	}
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.activity_schedule);
		initGlobalView();
		findView();
		setListenerOrAdapter();
		getButtonSchedule().setEnabled(false);
		getButtonSchedule().setBackgroundResource(R.color.gray5);
		setButtonNowYearAndMonth(schInitPosition);
		schedulePager.setCurrentItem(schInitPosition);
		new GetMyIDFBHelper().ensureSessionOpenAndDoSomething(ScheduleActivity.this);
		sensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
	}

	private void findView() {
		buttonNowYearAndMonth = (Button) findViewById(R.id.buttonNowYearAndMonth);
		schedulePager = (ViewPager) findViewById(R.id.schedulePager);
	}
	
	private void setListenerOrAdapter() {
		buttonNowYearAndMonth.setOnClickListener(new ButtonNowYearAndMonthClickListener());
		schedulePager.setAdapter(new SchedulePagerAdapter(getSupportFragmentManager()));
		schedulePager.setOnPageChangeListener(new SchedulePagerPageChangeListener());
	}
	
	private class ButtonNowYearAndMonthClickListener implements Button.OnClickListener {
		
		@Override
		public void onClick(View arg0) {
			DatePicker specificDatePicker = new DatePicker(ScheduleActivity.this);
			
			specificDatePicker.init(specificDay.get(Calendar.YEAR), specificDay.get(Calendar.MONTH),
					specificDay.get(Calendar.DATE), null);
			specificDatePicker.setCalendarViewShown(false);
			specificDatePicker.setDescendantFocusability(DatePicker.FOCUS_BLOCK_DESCENDANTS);
			new AlertDialog.Builder(ScheduleActivity.this)
			.setTitle("選擇日期")
			.setView(specificDatePicker)
			.setNegativeButton("取消", null)
			.setPositiveButton("確定", new DatePickerDialogPositiveOnClickListener(specificDatePicker))
			.show();
		}
		
		private class DatePickerDialogPositiveOnClickListener implements DialogInterface.OnClickListener {
			private DatePicker specificDatePicker;
			
			public DatePickerDialogPositiveOnClickListener(DatePicker specificDatePicker) {
				this.specificDatePicker = specificDatePicker;
			}

			@Override
			public void onClick(DialogInterface dialog, int which) {
				gotoSpecificDay(specificDatePicker.getYear(), specificDatePicker.getMonth(),
						specificDatePicker.getDayOfMonth());
			}
		}
	}
	
	private class SchedulePagerAdapter extends FragmentStatePagerAdapter {
		public SchedulePagerAdapter(FragmentManager fm) {
			super(fm);
		}

		@Override
		public int getCount() {
			return schSize;
		}

		@Override
		public Fragment getItem(int index) {
			if (scheduleFragmentTable.get(index) == null) {
				Calendar displayCal = Calendar.getInstance();
				
				displayCal.set(specificDay.get(Calendar.YEAR), specificDay.get(Calendar.MONTH),
						specificDay.get(Calendar.DATE));
				displayCal.add(Calendar.DAY_OF_WEEK, -(displayCal.get(Calendar.DAY_OF_WEEK) - 1));
				displayCal.add(Calendar.WEEK_OF_YEAR, index - schInitPosition);
				scheduleFragmentTable.put(index, new ScheduleFragment(displayCal, specificDay));
			}
			return scheduleFragmentTable.get(index);
		}
		
		@Override
		public int getItemPosition(Object object) {
			return POSITION_NONE;
		}
    }
	
	private class SchedulePagerPageChangeListener implements ViewPager.OnPageChangeListener {
		private boolean initFlag = false;
		
		@Override
		public void onPageScrollStateChanged(int arg0) {
		}

		@Override
		public void onPageScrolled(int arg0, float arg1, int arg2) {
		}

		@Override
		public void onPageSelected(int index) {
			if (initFlag) {
				setButtonNowYearAndMonth(index);
				isToday = false;
			}
			else
				initFlag = true;
		}
	}
	
	private void setButtonNowYearAndMonth(int index) {
		Calendar displayCal = Calendar.getInstance();
		String yearAndMonth;
		int startMonth;
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM", Locale.getDefault());
		
		displayCal.set(specificDay.get(Calendar.YEAR), specificDay.get(Calendar.MONTH),
				specificDay.get(Calendar.DATE));
		displayCal.add(Calendar.DAY_OF_WEEK, -(displayCal.get(Calendar.DAY_OF_WEEK) - 1));
		displayCal.add(Calendar.WEEK_OF_YEAR, index - schInitPosition);
		startMonth = displayCal.get(Calendar.MONTH);
		yearAndMonth = sdf.format(displayCal.getTime());
		displayCal.add(Calendar.DATE, 6);
		if (startMonth != displayCal.get(Calendar.MONTH))
			yearAndMonth += "~" + sdf.format(displayCal.getTime());
		buttonNowYearAndMonth.setText(yearAndMonth);
	}
	
	private class GetMyIDFBHelper extends FBHelper {
		private ProgressDialog proDialog;

		@Override
		protected void doAfterEnsureSessionOpen() {
			proDialog = ProgressDialog.show(ScheduleActivity.this, "查詢中", "正在查詢您的Facebook ID...");
			proDialog.setCancelable(false);
			fqlQuery("uid", "user", "uid = me()", null, null, null, null);
		}

		@Override
		protected void doAfterFqlQuery(Response response) {
			try {
				Bundle bundle = new Bundle();
				JSONArray dataJsonArr = response.getGraphObject().getInnerJSONObject().getJSONArray("data");
				
				bundle.putString("myFBID", dataJsonArr.getJSONObject(0).getString("uid"));
				getIntent().putExtras(bundle);
				new GetMySchedule().execute(getIntent().getExtras().getString("myFBID"));
			} catch (JSONException e) {
				e.printStackTrace();
			}
		}
		
		private class GetMySchedule extends GetMyScheduleHelper {
			
			@Override
			protected void onPreExecute() {
				proDialog.setMessage("正在取得您的行程表...");
			}

			@Override
			protected void onPostExecute(String jsonString) {
				try {
					JSONArray respJsonArr;
					
					for (int i=0; i<=6; i++)
						dayCalDatasMap.put(i, new HashSet<CalendarTextData>());
					if (!jsonString.equals("null")) {
						respJsonArr = new JSONArray(jsonString);
						for (int i=0; i<respJsonArr.length(); i++) {
							CalendarTextData calTextData = CalendarTextDataFactory.newByJsonObject(
									respJsonArr.getJSONObject(i));
							
							dayCalDatasMap.get(calTextData.getDay()).add(calTextData);
						}
					}
					proDialog.cancel();
				} catch (JSONException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	@Override
	protected void onResume() {
		super.onResume();
		sensorManager.registerListener(ssEventListener,
				sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
	}
	
	@Override
    protected void onPause() {
		super.onPause();
		sensorManager.unregisterListener(ssEventListener);
	}
	
	private class ShakeSensorEventListener implements SensorEventListener {

		@Override
		public void onAccuracyChanged(Sensor sensor, int accuracy) {
		}

		@Override
		public void onSensorChanged(SensorEvent event) {
			if (!isToday && (event.values[0] > 8 || event.values[0] < -8)) {
				Calendar today = Calendar.getInstance();
				
				gotoSpecificDay(today.get(Calendar.YEAR), today.get(Calendar.MONTH), today.get(Calendar.DATE));
				isToday = true;
			}
		}
	}
	
	private void gotoSpecificDay(int theYear, int theMonth, int theDate) {
		isToday = false;
		specificDay.set(theYear, theMonth, theDate);
		setButtonNowYearAndMonth(schInitPosition);
		scheduleFragmentTable.clear();
		schedulePager.setCurrentItem(schInitPosition);
		schedulePager.getAdapter().notifyDataSetChanged();
	}
	
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (resultCode == RESULT_OK) {
			switch (requestCode) {
				default:
					Session.getActiveSession().onActivityResult(
							ScheduleActivity.this, requestCode, resultCode, data);
			}
		}
	}
}